/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * Copyright (c) 2019 STMicroelectronics International N.V. 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without 
  * modification, are permitted, provided that the following conditions are met:
  *
  * 1. Redistribution of source code must retain the above copyright notice, 
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. Neither the name of STMicroelectronics nor the names of other 
  *    contributors to this software may be used to endorse or promote products 
  *    derived from this software without specific written permission.
  * 4. This software, including modifications and/or derivative works of this 
  *    software, must execute solely and exclusively on microcontroller or
  *    microprocessor devices manufactured by or for STMicroelectronics.
  * 5. Redistribution and use of this software other than as permitted under 
  *    this license is void and will automatically terminate your rights under 
  *    this license. 
  *
  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 
  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 
  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include "MQTTPacket.h"
#include "mqttclient.h"
#include "usart.h"
#include "OLED_I2C.h"
#include "gpio.h"
#include "string.h"
#include "rtc.h"
#include "tim.h"
#include "dht11.h"
#include <stdio.h>
//#include "interface.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */     

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
extern TimeandDate TD;
extern uint8_t alarmmem[36];
extern uint8_t setting[14];
extern MQTTString topicString;
/* USER CODE END Variables */
osThreadId PublishTaskHandle;
osThreadId mainTaskHandle;
osThreadId HC_RS04Handle;

osSemaphoreId HC_RS04Sem;
osSemaphoreId PublishSem;
osMessageQId RxQueueHandle;
osTimerId DHT11Handle;
osTimerId PingHandle;
osTimerId RTCHandle;
osTimerId Action1Handle;
osTimerId Action2Handle;
osTimerId Action3Handle;
osTimerId Action4Handle;

GPIO_InitTypeDef GPIO_InitStruct0;
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
void action(uint8_t arg);
void inttochar(uint8_t *tmp,uint8_t *arg1,uint8_t *arg2);
void HC_RS04(void const * argument);
void ActionTimer1(void const * argument);
void ActionTimer2(void const * argument);
void ActionTimer3(void const * argument);
void ActionTimer4(void const * argument);
/* USER CODE END FunctionPrototypes */


void Publish(void const * argument);
void maintask(void const * argument);
void PingTimer(void const * argument);
void DHT11Timer(void const * argument);
extern void RTC_Callback(void const * argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
       
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */

	/* definition and creation of mainTask */
  osThreadDef(mainTask, maintask, osPriorityNormal, 1, 300);
  mainTaskHandle = osThreadCreate(osThread(mainTask), NULL);
	
	
  /* definition and creation of PublishTask */
  osThreadDef(PublishTask, Publish, osPriorityNormal, 1, 128);
  PublishTaskHandle = osThreadCreate(osThread(PublishTask), NULL);


  /* definition and creation of IOTask */
  

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	osThreadDef(HC_RS04Task, HC_RS04, osPriorityNormal, 2, 64);
  HC_RS04Handle = osThreadCreate(osThread(HC_RS04Task), NULL);
	
	osSemaphoreDef(semaphore1);
	HC_RS04Sem= osSemaphoreCreate(osSemaphore(semaphore1), 1);
	
	osSemaphoreDef(semaphore2);
	PublishSem= osSemaphoreCreate(osSemaphore(semaphore2), 1);
  /* USER CODE END RTOS_THREADS */

  /* Create the queue(s) */
  /* definition and creation of RxQueue */
	
  osMessageQDef(RxQueue, 16, uint32_t);
  RxQueueHandle = osMessageCreate(osMessageQ(RxQueue), NULL);

  /* definition and creation of PublishQueue */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
	osTimerDef(dht11timer,DHT11Timer);
	DHT11Handle=osTimerCreate(osTimer(dht11timer),osTimerPeriodic,NULL);
	
	osTimerDef(pingtimer,PingTimer);
	PingHandle=osTimerCreate(osTimer(pingtimer),osTimerPeriodic,NULL);
	
	osTimerDef(rtctimer,RTC_Callback);
	RTCHandle=osTimerCreate(osTimer(rtctimer),osTimerPeriodic,NULL);
	
	osTimerDef(feedtimer,ActionTimer1);
	Action1Handle=osTimerCreate(osTimer(feedtimer),osTimerOnce,NULL);
	
	osTimerDef(watertimer,ActionTimer2);
	Action2Handle=osTimerCreate(osTimer(watertimer),osTimerOnce,NULL);
	
	osTimerDef(cleantimer,ActionTimer3);
	Action3Handle=osTimerCreate(osTimer(cleantimer),osTimerOnce,NULL);
	
	osTimerDef(killtimer,ActionTimer4);
	Action4Handle=osTimerCreate(osTimer(killtimer),osTimerOnce,NULL);
	
  /* USER CODE END RTOS_QUEUES */
}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used 
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */




/* USER CODE BEGIN Header_Publish */
/**
* @brief Function implementing the PublishTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Publish */
void Publish(void const * argument)
{
	osDelay(200);
  /* USER CODE BEGIN Publish */
	uint8_t txBuf1[64];
	//uint8_t buflen;
  /* Infinite loop */
  for(;;)
  {
		uint8_t i;
		//publish("topic2","publish running",0);
		osSemaphoreWait (PublishSem, osWaitForever);
		
		txBuf1[0]=0x31;
		txBuf1[1]=0x31;
		for(i=0;i<14;i++)
			txBuf1[i+2]=setting[i];
		uint8_t tx[]={0X32,0X30,TD.year[0],TD.year[1],TD.month[0],TD.month[1],TD.day[0],TD.day[1],
			TD.hour[0],TD.hour[1],TD.minute[0],TD.minute[1]};
		//publish("t0001",(char*)tx,0);
		for(i=0;i<12;i++)
			txBuf1[i+16]=tx[i];
		for(i=0;i<36;i++)
			txBuf1[i+28]=alarmmem[i];
			
		unsigned char buf[80];
		topicString.cstring ="t0001";
		int len = 0;
		len = MQTTSerialize_publish(buf,80, 0, 0, 0, 0,topicString , txBuf1, 64);
		HAL_UART_Transmit(&huart1,buf,len,10);
		
    osThreadYield();
  }
  /* USER CODE END Publish */
}

/* USER CODE BEGIN Header_maintask */
/**
* @brief Function implementing the mainTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_maintask */
void maintask(void const * argument)
{
  /* USER CODE BEGIN maintask */
	uint8_t flag;
	flash_read(50,&flag,1);
	if(flag==0x55)
	{
		flash_read(0,&alarmmem[0],36);
		flash_read(36,&setting[0],14);
	}
	uint8_t* rxBuf;
	//uint8_t i;
	osTimerStart(RTCHandle,1000);
	osTimerStart(PingHandle,30000);
	osTimerStart(DHT11Handle,3000);
	
  /* Infinite loop */
  for(;;)
  {
		osDelay(100);
		publish("t0001","recieve",0);

		rxBuf=osMessageGet(RxQueueHandle,osWaitForever).value.p;

		switch(rxBuf[0])
		{
			case 0x31:
				switch(rxBuf[1])
				{
					case 0x31:
						action(1);
						break;
					case 0x32:
						action(2);
						break;
					case 0x33:
						setting[1]=rxBuf[2];
						break;
					case 0x34:
						setting[3]=rxBuf[2];
						break;
					case 0x35:
						setting[0]=rxBuf[3];
						setalarm(&rxBuf[2]);
						break;
					case 0x36:
						setting[2]=rxBuf[3];
						setalarm(&rxBuf[2]);
						break;
				}
				break;
			case 0x32:
				switch(rxBuf[1])
				{	
					case 0x31:
						setting[5]=rxBuf[2];
						break;
					case 0x32:
						setting[6]=rxBuf[2];
						setting[7]=rxBuf[3];
						break;
				}
				break;
			case 0x34:
				switch(rxBuf[1])
				{
					case 0x31:
						osSemaphoreRelease (HC_RS04Sem);
						osDelay(50);
						if(setting[4]==0x32)
							action(3);
						else if(setting[4]==0x31)
							EXTI->IMR|=1<<3;
					break;
					case 0x32:
						osSemaphoreRelease (HC_RS04Sem);
						osDelay(50);
						if(setting[4]==0x32)
							action(4);
						else if(setting[4]==0x31){
							EXTI->IMR|=1<<3;
						}
					break;
					case 0x33:
						setalarm(&rxBuf[2]);
					break;
					case 0x34:
						setting[13]=rxBuf[2];	
					break;
					case 0x35:
						setting[12]=rxBuf[2];
					break;
				}
				break;
			case 0x35:
				if(rxBuf[1]==0x31)
					OLED_ON();
				else
					OLED_OFF();
			break;
			case 0x36:
				osSemaphoreRelease (HC_RS04Sem);
				osDelay(50);
				osSemaphoreRelease (PublishSem);
			break;
			case 0x37:
				settime(&rxBuf[1]);
			break;
			default:
				break;
		}
		uint8_t txBuf[52];
		for(uint8_t k=0;k<36;k++)txBuf[k]=alarmmem[k];
		for(uint8_t k1=0;k1<14;k1++)txBuf[k1+36]=setting[k1];
		txBuf[50]=0x55;
		if(flash_write((uint32_t *)&txBuf[0],52)==0)publish("t0003","fail6",0);
		osThreadYield();
  }
  /* USER CODE END maintask */
}

/* USER CODE BEGIN Header_IOtask */

void HC_RS04(void const * argument)
{
	float distance;
	int tim_us=0;
	for(;;)
	{
		osDelay(600);
		osSemaphoreWait (HC_RS04Sem, osWaitForever);
		tim_us=getdistance();
		distance=0.034*tim_us/2;
		if(distance<30){
			//publish("topic2","yes",0);
			setting[4]=0x31;}
		else {
			//publish("topic2","no",0);
			setting[4]=0x32;}
		osThreadYield();
	}
}
/* USER CODE END Header_IOtask */

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void DHT11Timer(void const * argument)
{
	DHT11_Data_TypeDef DHT11={0};
	__HAL_RTC_SECOND_DISABLE_IT (&hrtc,RTC_IT_SEC);
	if(Read_DHT11(&DHT11)){
	publish("t0001","fail",0);}
	__HAL_RTC_SECOND_ENABLE_IT (&hrtc,RTC_IT_SEC);
	setting[8]=DHT11.temp_int;
	setting[9]=DHT11.temp_deci;
	setting[10]=DHT11.humi_int;
	setting[11]=DHT11.humi_deci;
	inttochar(&DHT11.temp_char[0],&DHT11.temp_int,&DHT11.temp_deci);
	
	inttochar(&DHT11.humi_char[0],&DHT11.humi_int,&DHT11.humi_deci);
	
	
	OLED_ShowStr(48,4,DHT11.temp_char,2);
	OLED_ShowStr(48,6,DHT11.humi_char,2);
	if(setting[5]==0x31)
	{
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET);
	}else HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);;
}

void PingTimer(void const * argument)
{
	//publish("t0003","timer running",1);
	Ping();
}

void ActionTimer1(void const * argument)
{
	__HAL_TIM_SET_COMPARE ( &htim2,TIM_CHANNEL_1,50);
	osTimerStop(Action1Handle);
}

void ActionTimer2(void const * argument)
{
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
	osTimerStop(Action2Handle);
}

void ActionTimer3(void const * argument)
{
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
	osTimerStop(Action3Handle);
}

void ActionTimer4(void const * argument)
{
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
	osTimerStop(Action4Handle);
}

void action(uint8_t arg)
{
	
	switch(arg)
	{
		case 1:
			__HAL_TIM_SET_COMPARE (&htim2,TIM_CHANNEL_1,250);
			osTimerStart(Action1Handle,setting[1]*200);
			break;
		case 2:
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
			osTimerStart(Action2Handle,setting[3]*200);
			break;
		case 3:
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
			osTimerStart(Action3Handle,2500);
			EXTI->IMR|=1<<4;
			break;
		case 4:
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
			osTimerStart(Action4Handle,setting[13]*60000);
			EXTI->IMR|=1<<4;
			break;
	}
}

void inttochar(uint8_t *tmp,uint8_t *arg1,uint8_t *arg2)
{
	uint8_t sAscii[] = "0123456789";
	//uint8_t *tmp;
	uint8_t i=0;
	uint8_t j;
	uint8_t k;
	while(*arg1>=10)
	{
		*arg1-=10;
		i++;
		
	}
	j=*arg1;
	k=*arg2;
	if(i!=0){
		tmp[0]=sAscii[i];
		tmp[1]=sAscii[j];
		tmp[2]='.';
		tmp[3]=sAscii[k];
		tmp[4]='\0';
	}else{
		tmp[0]=sAscii[j];
		tmp[1]='.';
		tmp[2]=sAscii[k];
		tmp[3]='\0';}
	//return tmp;
}	


/* USER CODE END Application */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
